/**
 * 
 */
package org.yelongframework.json.gson.adapter;

import java.io.IOException;
import java.text.ParseException;
import java.util.Date;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yelongframework.commons.time.DateUtil;
import org.yelongframework.lang.Nullable;

import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;

/**
 * java.util.Date类型适配器。 对于Date的属性在序列化或者反序列化时，遇到“空”值时使用填补值来返回。
 * 可以设置序列化时Date的格式与反序列化时如果解析这个字符串为Date
 * 
 * @since 1.0.0
 */
public class DateTypeAdapter extends CloneableTypeAdapter<Date> {

	private static final Logger log = LoggerFactory.getLogger(DateTypeAdapter.class);

	/** 序列化null值填补 */
	private String serializationNullPadding;

	/** 反序列化null值填补 */
	private Date deserializationNullPadding;

	/** 反序列化时对Date的解析格式 */
	private String[] parsePatterns = DateUtil.parsePatterns;

	/** 转换JSON时对Date的格式化格式 */
	@Nullable
	private String formatPattern = DateUtil.YYYY_MM_DD_HH_MM_SS;

	// ==================================================构造器==================================================

	public DateTypeAdapter() {
		this("", null);
	}

	/**
	 * @param serializationNullPadding   序列化null值填补
	 *                                   当String类型进行转换json时，如果这个属性值为null则使用{@link #serializationNullPadding}来替换
	 * @param deserializationNullPadding 反序列化null值填补 反序列化null值填补
	 *                                   当json进行转换String类型时，如果这个属性值为null则使用{@link #deserializationNullPadding}来替换
	 */
	public DateTypeAdapter(String serializationNullPadding, Date deserializationNullPadding) {
		this.serializationNullPadding = serializationNullPadding;
		this.deserializationNullPadding = deserializationNullPadding;
	}

	// ==================================================序列化null值填补==================================================

	/**
	 * @return 序列化null值填补
	 */
	public String getSerializationNullPadding() {
		return serializationNullPadding;
	}

	/**
	 * @param serializationNullPadding 序列化null值填补
	 * @return this
	 */
	public DateTypeAdapter setSerializationNullPadding(String serializationNullPadding) {
		this.serializationNullPadding = serializationNullPadding;
		return this;
	}

	// ==================================================反序列化null值填补==================================================

	/**
	 * @return 反序列化null值填补
	 */
	public Date getDeserializationNullPadding() {
		return deserializationNullPadding;
	}

	/**
	 * @param deserializationNullPadding 反序列化null值填补
	 * @return this
	 */
	public DateTypeAdapter setDeserializationNullPadding(Date deserializationNullPadding) {
		this.deserializationNullPadding = deserializationNullPadding;
		return this;
	}

	// ==================================================反序列化时对Date的解析格式==================================================

	/**
	 * @return 反序列化时对Date的解析格式
	 */
	public String[] getParsePatterns() {
		return parsePatterns;
	}

	/**
	 * @param parsePatterns 反序列化时对Date的解析格式
	 * @return this
	 */
	public DateTypeAdapter setParsePatterns(String... parsePatterns) {
		if (ArrayUtils.isEmpty(parsePatterns)) {
			throw new IllegalArgumentException("parsePatterns cannot be empty");
		}
		this.parsePatterns = parsePatterns;
		return this;
	}

	// ==================================================转换JSON时对Date的格式化格式==================================================

	/**
	 * @return 转换JSON时对Date的格式化格式
	 */
	public String getFormatPattern() {
		return formatPattern;
	}

	/**
	 * @param formatPattern 转换JSON时对Date的格式化格式
	 * @return this
	 */
	public DateTypeAdapter setFormatPattern(String formatPattern) {
		this.formatPattern = formatPattern;
		return this;
	}

	// ==================================================写==================================================

	@Override
	public void write(JsonWriter out, Date value) throws IOException {
		if (value == null) {
			out.value(serializationNullPadding);
			return;
		}
		if (null == formatPattern) {
			out.value(value.toString());
		} else {
			out.value(DateFormatUtils.format(value, formatPattern));
		}
	}

	// ==================================================读==================================================

	@Override
	public Date read(JsonReader in) throws IOException {
		if (in.peek() == JsonToken.NULL) {
			in.nextNull();
			return deserializationNullPadding;
		}
		String str = in.nextString();
		try {
			return DateUtils.parseDate(str, parsePatterns);
		} catch (ParseException e) {
			log.debug("日期解析失败", e);
			return null;
		}
	}

	// ==================================================克隆==================================================

	@Override
	public DateTypeAdapter clone() throws CloneNotSupportedException {
		DateTypeAdapter dateTypeAdapter = new DateTypeAdapter(serializationNullPadding, deserializationNullPadding);
		dateTypeAdapter.setFormatPattern(formatPattern);
		dateTypeAdapter.setParsePatterns(parsePatterns);
		return dateTypeAdapter;
	}

}
